home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gigantic Games 2
/
Gigantic Games 2.iso
/
pc
/
_z_
/
zorkmachine
/
mem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-23
|
5KB
|
307 lines
/*
* @(#)mem.c 2.24
*/
# include "zmachine.h"
#ifdef AMIGA
#undef NULL
#define NULL 0L
#endif
# define LOCK 0xffffffffL
UBYTE *main_p; /* main memory pointer */
int main_l; /* main memory len in pages */
struct header *main_h; /* header pointer */
struct virt_page *pc_page; /* page of current pc */
struct virt_page main_page; /* page control for main memory */
struct virt_page *c_page; /* current active page */
struct virt_page *virt_p; /* the virtual memory array */
struct address pc; /* program counter */
unsigned long lruc = 0; /* LRU counter */
/************************************************************************/
/* find free page */
struct virt_page *find_page()
{
register struct virt_page *u, *v;
register long t;
for(v = virt_p, t = LOCK; v->page != -1; v++)
if (v->lru < t)
{
t = v->lru;
u = v;
}
return(u);
}
/* load a page */
UBYTE *load_page(page)
register WORD page;
{
register struct virt_page *v;
if (page != c_page->page)
{
lruc++;
for (v = virt_p; v->page != -1; v++)
{
if (v->page == page)
{
if (pc_page->page != page)
v->lru = lruc;
c_page = v;
return(c_page->paddr);
}
}
c_page = find_page();
c_page->page = page;
c_page->lru = lruc;
read_story(c_page->page, 1, c_page->paddr);
}
return(c_page->paddr);
}
/* load page for current pc */
void load_code()
{
pc.segment += pc.offset >> 9; /* pc.offset may be negative */
pc.offset &= 0x1ff;
if (pc.segment != pc_page->page)
{
pc_page->lru = lruc;
if (pc.segment >= main_l)
{
load_page(pc.segment);
pc_page = c_page;
pc_page->lru = LOCK;
}
else
{
main_page.page = pc.segment;
main_page.paddr = main_p+ptob(pc.segment);
pc_page = &main_page;
}
}
}
/* page to byte address */
long ptob(page)
UWORD page;
{
return(((long)page << (long)9) & 0x1ffffL);
}
/* byte to page address */
UWORD btop(byte)
long byte;
{
return((byte & 0x1ff ? (byte >> 9)+1:(byte >> 9)) & 0xff);
}
/* get word */
UWORD word_get(p)
UBYTE *p;
{
register UWORD i;
i = *p++ << 8;
return(i | *p);
}
/* put word */
void word_put(p, d)
UBYTE *p; register UWORD d;
{
p[1] = d & 0xff;
p[0] = d >> 8;
}
/* fetch byte data */
UBYTE fetchb_data(a)
register struct address *a;
{
UBYTE *load_page();
register UBYTE r;
if (a->segment < main_l)
r = main_p[ptob(a->segment) | a->offset];
else
r = load_page(a->segment)[a->offset];
if (++(a->offset) == 0x200)
{
a->offset = 0;
(a->segment)++;
}
return(r);
}
/* fetch word data */
UWORD fetchw_data(a)
struct address *a;
{
register UWORD r;
r = fetchb_data(a);
return((r << 8) | fetchb_data(a));
}
/* fetch next byte from pc */
UBYTE fetchb_op()
{
register UBYTE r;
r = pc_page->paddr[pc.offset];
if (++pc.offset >= 0x200)
load_code();
return(r);
}
/* fetch next word from pc */
UWORD fetchw_op()
{
register UWORD r;
r = fetchb_op() << 8;
return(r | fetchb_op());
}
/* byte address to virtual address */
void baddr_to_vaddr(vaddress, baddress)
register struct address *vaddress; register UWORD baddress;
{
vaddress->segment = (baddress >> 9) & 0xff;
vaddress->offset = baddress & 0x1ff;
}
/* word address to virtual address */
void waddr_to_vaddr(vaddress, waddress)
struct address *vaddress; register UWORD waddress;
{
vaddress->segment = (waddress >> 8) & 0xff;
vaddress->offset = (waddress & 0xff) * 2;
}
/* initialize mmu */
#if defined(minix)
extern int brk();
extern char *sbrk();
static char *oldbrk = NULL;
static char *lmalloc(s)
long s;
{
char *m;
if (!oldbrk)
oldbrk = sbrk(0);
m = sbrk(0);
if (brk(m + s + 0x2000) != 0)
{
brk(m);
return(NULL);
}
else
{
brk(m + s);
return(m);
}
}
static free(p)
char *p;
{
brk(oldbrk);
}
#endif
void mmu_init(h)
struct header *h;
{
long virt_l;
int i;
if (main_p = (UBYTE *)lmalloc(btop((long)word_get(h->len) * 2L) * 512L))
{
main_l = btop((long)word_get(h->len) * 2L);
virt_l = 2;
if (!(virt_p = (struct virt_page *)lmalloc((0x200L +
sizeof(struct virt_page)) * 2 +
sizeof(struct virt_page))))
{
free(main_p);
goto low_mem;
}
}
else
{
low_mem:
if ((main_p = (UBYTE *)
lmalloc((long)btop((long)word_get(h->minmem)) * 512L))
== NULL)
no_mem_error();
main_l = btop((long)word_get(h->minmem));
for (virt_l = btop((long)word_get(h->len) * 2L -
(long)word_get(h->minmem));
virt_l >= 2 && virt_p == NULL; virt_l--)
virt_p = (struct virt_page *)lmalloc((long)
(virt_l * (0x200L +
sizeof(struct virt_page)) +
sizeof(struct virt_page)));
if (virt_l < 2)
no_mem_error();
}
for (i = 0; i < virt_l; i++)
{
virt_p[i].page = -2;
virt_p[i].lru = 0L;
virt_p[i].paddr = (UBYTE *)virt_p +
(long)(sizeof(struct virt_page) *
(virt_l + 1L) + 0x200L * (long)i);
}
virt_p[i].page = -1;
pc_page = c_page = virt_p;
main_h = (struct header *)main_p;
}